﻿using System;
//using System.Linq;
//using System.Configuration;
//using System.Collections.Generic;
using HarmonyLib;
using TaleWorlds.Core;
using TaleWorlds.MountAndBlade;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.GameMenus;
using TaleWorlds.CampaignSystem.Overlay;
using TaleWorlds.CampaignSystem.SandBox;
//using TaleWorlds.CampaignSystem.SandBox.CampaignBehaviors;
//using TaleWorlds.CampaignSystem.SandBox.GameComponents;
//using TaleWorlds.CampaignSystem.SandBox.GameComponents.Party;
//using TaleWorlds.Localization;
//using TaleWorlds.SaveSystem;
//using TaleWorlds.Library;


//[GameMenuInitializationHandler("menu_ponder_plunder")]
//private static void menu_ponder_plunder_on_init(MenuCallbackArgs args)
//{
//    args.MenuContext.SetBackgroundMeshName("wait_besieging");
//}

namespace VsMod_PlunderSettlements
{
    public class VsMod_PlunderSettlements_SubModule : MBSubModuleBase
    {
        protected override void OnSubModuleLoad()
        {
            base.OnSubModuleLoad();

            var harmony = new Harmony("YarYarMePlundrAndMeRum");
            harmony.PatchAll();
        }

        protected override void OnBeforeInitialModuleScreenSetAsRoot()
        {
            base.OnBeforeInitialModuleScreenSetAsRoot();
            InformationManager.DisplayMessage(new InformationMessage("Vaeringjar's Plunder Settlements [v1.1]"));
        }

        protected override void OnGameStart(Game game, IGameStarter gameStarterObject)
        {
            if (!(game.GameType is Campaign)) // basilisk mod
                return;
            CampaignGameStarter gameInitializer = (CampaignGameStarter)gameStarterObject;

            gameInitializer.AddBehavior(new VsMod_PlunderSettlements_Behaviour());
        }
    }

    public class VsMod_PlunderSettlements_Behaviour : CampaignBehaviorBase
    {

        [GameMenuInitializationHandler("menu_ponder_plunder")]
        private static void menu_ponder_plunder_on_init(MenuCallbackArgs args)
        {
            args.MenuContext.SetBackgroundMeshName("wait_besieging");
        }

        private void OnSessionLaunched(CampaignGameStarter obj)
        {
            //obj.AddGameMenu("menu_ponder_plunder", Settlement.CurrentSettlement.Name + " has fallen to your troops. You may station a garrison here to defend it against enemies who may try to recapture it.", null, GameOverlays.MenuOverlayType.None, GameMenu.MenuFlags.none, null);
                // right, here the variable won't get updated... the text will be the same all the time...obj.AddGameMenuOption("menu_ponder_plunder","plunder_settlement","Have your troops plunder " + Settlement.CurrentSettlement.Name, null, game_menu_plunder_settlement_on_consequence,true,0,false);
            //obj.AddGameMenuOption("menu_ponder_plunder", "plunder_settlement", "Have your troops plunder " + Settlement.CurrentSettlement.Name, null, game_menu_plunder_settlement_on_consequence, true, 0, false);

            obj.AddGameMenu("menu_ponder_plunder", "The settlement has fallen to your troops. You may station a garrison here to defend it against enemies who may try to recapture it.", null, GameOverlays.MenuOverlayType.None, GameMenu.MenuFlags.none, null);
            obj.AddGameMenuOption("menu_ponder_plunder","plunder_settlement","Have your troops plunder the settlement", null, game_menu_plunder_settlement_on_consequence,true,0,false);
            obj.AddGameMenuOption("menu_ponder_plunder", "plunder'n't", "Continue...", null, game_menu_plundernt_settlement_on_consequence, true, 1, false);
        }

        //private bool game_menu_plunder_settlement_on_condition(MenuCallbackArgs args)
        //{
        //    return true;
        //}
        private void game_menu_plunder_settlement_on_consequence(MenuCallbackArgs args)
        {
            // # soldiers go on a looting spree # soldiers take a % of loot, gaining morale
            // # causes collateral damage # lose relations with every lord of native culture
            // # convert prosperity into gold # lose loyalty, security, etc...  # buildings destroyed

            Settlement settlement = Settlement.CurrentSettlement;

            // -75% security
            float old_security = Settlement.CurrentSettlement.Town.Security;
            int new_security = (int)Math.Ceiling(old_security * 0.25f);
            Settlement.CurrentSettlement.Town.Security = new_security;

            // -75% loyalty
            float old_loyalty = Settlement.CurrentSettlement.Town.Loyalty;
            int new_loyalty = (int)Math.Ceiling(old_loyalty * 0.25f);
            Settlement.CurrentSettlement.Town.Loyalty = new_loyalty;

            // -25% prosperity
            float old_prosperity = Settlement.CurrentSettlement.Prosperity;
            float new_prosperity = old_prosperity * 0.75f; // 25% of prosperity plundered
            Settlement.CurrentSettlement.Prosperity = new_prosperity;
            int plundered_prosperity_wealth = (int)Math.Ceiling(( old_prosperity - new_prosperity ) * 1000f ); // if 1 prosperity = 1000 gold; 

            // -80% merchant denars
            int plundered_merchant_coin = 0;
            if ( settlement.IsTown == true)
            {
                plundered_merchant_coin = (int)Math.Ceiling(settlement.Town.Gold * -0.8f);
                settlement.Town.ChangeGold(plundered_merchant_coin);// remove gold from city merchant
            }

            // plunder: 50% for troops, 50% for commander; 
            int commanders_share = (int)Math.Ceiling( 0.5f * ( plundered_merchant_coin + plundered_prosperity_wealth ) ); 
            Hero.MainHero.ChangeHeroGold((int)commanders_share); // ...displays no message
                // MainHero won't work for AI
            //GiveGoldAction.ApplyForSettlementToCharacter(settlement, Hero.MainHero, plundered_gold); // this easily results in a city's merchants having 0 coin...

            // Gain party morale
            int loot_morale = (int)Math.Ceiling(commanders_share / 4000f) ;
            //MobileParty.MainParty.MoraleExplainer.AddLine("Shared Plunder", loot_morale); // does nothing
            MobileParty.MainParty.RecentEventsMorale += loot_morale;
                // MainParty won't work for AI

            // Collateral damage (building levels lowered)
            //

            // report
            InformationManager.DisplayMessage(new InformationMessage("Sacking " + Settlement.CurrentSettlement + " has decreased its prosperity from " + (int)Math.Ceiling(old_prosperity) + " to " + (int)Math.Ceiling(new_prosperity) +
                ". Streets are in anarchy, security has fallen from " + (int)Math.Ceiling(old_security) + " to " + new_security +
                ". People resent their conquerors, loyalty has been reduced from " + (int)Math.Ceiling(old_loyalty) + " to " + new_loyalty + "."));
            InformationManager.DisplayMessage(new InformationMessage("You and your men assess the collected loot, your share being worth " + commanders_share + " denars. Party morale as increased!"));

            // lose relations with notables 
            foreach (Hero notablePerson in Settlement.CurrentSettlement.Notables) // credit to mod 188
            {
                ChangeRelationAction.ApplyPlayerRelation(notablePerson, -20, false, true);
            }
            // Lose relations with clans of culture
            int count = 0;
            if (settlement.IsTown)
            {
                foreach (Clan clan in Clan.All)
                {
                    if (clan.Leader.Culture == settlement.Culture && clan.Leader != Hero.MainHero)
                    {
                        ChangeRelationAction.ApplyPlayerRelation(clan.Leader, -10, true, true);
                        count = count + 1;
                    }
                }
                // report
                InformationManager.DisplayMessage(new InformationMessage("Your actions anger " + Settlement.CurrentSettlement.Notables.Count + " local notables and " + count + " clans of " + settlement.Culture + " culture."));

                GameMenu.SwitchToMenu("town"); // behold this beauty of a workaround (I'm sorry...)
            }
            if (settlement.IsCastle)
            {
                foreach (Clan clan in Clan.All)
                {
                    if (clan.Leader.Culture == settlement.Culture && clan.Leader != Hero.MainHero)
                    {
                        ChangeRelationAction.ApplyPlayerRelation(clan.Leader, -5, true, true);
                        count = count + 1;
                    }
                }
                // report
                InformationManager.DisplayMessage(new InformationMessage("Your actions anger " + count + " clans of " + settlement.Culture + " culture."));
                
                GameMenu.SwitchToMenu("castle"); // behold this beauty of a workaround (I'm sorry...)
            }
            //GameMenu.ExitToLast(); // stops all other menus from working fml // saving and reloading... doesn't do shit
            //GameMenu.SwitchToMenu("town");
            //GameMenu.SwitchToMenu("castle");

        }
        private void game_menu_plundernt_settlement_on_consequence(MenuCallbackArgs args)
        {
            //GameMenu.ExitToLast(); // yeah fml

            if (Settlement.CurrentSettlement.IsTown )
            {
                GameMenu.SwitchToMenu("town");
            }
            if (Settlement.CurrentSettlement.IsCastle )
            {
                GameMenu.SwitchToMenu("castle");
            }
        }

        public override void RegisterEvents()
        {
            CampaignEvents.OnSessionLaunchedEvent.AddNonSerializedListener(this, new Action<CampaignGameStarter>(this.OnSessionLaunched)); // credit basilisk mod
            //CampaignEvents.WeeklyTickEvent.AddNonSerializedListener(this, this.trackDaily); // credit basilisk mod
            //CampaignEvents.MapEventEnded.AddNonSerializedListener(this, new Action<MapEvent>(OnMapEvent)); // credit mod 188
        }
        public override void SyncData(IDataStore dataStore)
        {
        }
    }

    [HarmonyPatch(typeof(GameMenusCallbacks), "menu_settlement_taken_on_init")]
    internal class VsMod_PlunderSettlements_Override1
    {
        public static void Postfix() // MenuCallbackArgs args
        {
            if (MobileParty.MainParty.Army == null || MobileParty.MainParty.Army.LeaderParty == MobileParty.MainParty)
            {
                //GameMenu.ActivateGameMenu("menu_ponder_plunder"); // doesn't work
                GameMenu.SwitchToMenu("menu_ponder_plunder"); // :3
            }
        }
    }
}

// public void AddGameMenuOption(string menuId, string optionId, string optionText, GameMenuOption.OnConditionDelegate condition, 
//                                                            GameMenuOption.OnConsequenceDelegate consequence, bool isLeave = false, int index = -1, bool isRepeatable = false);
// menuID = "village" "town" "castle" ?city_conqured? //
/*
            // AddGameMenuOption
            obj.AddGameMenuOption("town", "plunder_settlement", "Plunder City", game_menu_plunder_settlement_on_condition, this.game_menu_plunder_settlement_on_consequence, false, 99, false);
            obj.AddGameMenuOption("castle", "plunder_settlement", "Plunder Castle", game_menu_plunder_settlement_on_condition, this.game_menu_plunder_settlement_on_consequence, false, 99, false);
            // tests
                // main siege screen
            obj.AddGameMenuOption("menu_siege_strategies", "plunder_settlement", "Plunder WIP 001", game_menu_plunder_settlement_on_condition, this.game_menu_plunder_settlement_on_consequence, false, 99, false);
                // leave siege menu
            obj.AddGameMenuOption("menu_siege_strategies_break_siege", "plunder_settlement", "Plunder WIP 002", game_menu_plunder_settlement_on_condition, this.game_menu_plunder_settlement_on_consequence, false, 99, false);
                // ?
            obj.AddGameMenuOption("leave", "plunder_settlement", "Plunder WIP 003", game_menu_plunder_settlement_on_condition, this.game_menu_plunder_settlement_on_consequence, false, 99, false);
*/
//campaignGameSystemStarter.AddWaitGameMenu("menu_siege_strategies", "{=DpxfKh13}{CURRENT_STRATEGY}", new OnInitDelegate(this.game_menu_siege_strategies_on_init), null, null, new OnTickDelegate(this.game_menu_siege_strategies_on_tick),
// GameMenu.SwitchToMenu("");

